package dnl.util.ui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

/**
 * A panel that hides its central part till the user expands it.
 * 
 * @author daniel
 * 
 */
public class ExpandingPanel extends JPanel {

	private JPanel topPanel;

	private JPanel contentPanel;

	private static ImageIcon closedIcon;

	private static ImageIcon openedIcon;

	private boolean expanded;
	
	private JButton jb;

	private ExpansionCallback callback;
	
	/**
	 * 
	 * @param contentPanel
	 *            the actual content.
	 */
	public ExpandingPanel(JPanel contentPanel) {
		super(new BorderLayout());
		this.contentPanel = contentPanel;
		contentPanel.setBorder(BorderFactory.createEtchedBorder());
		initIcons();
		jb = new JButton(closedIcon);
		jb.setPreferredSize(new Dimension(closedIcon.getIconWidth(), closedIcon.getIconHeight()));
		topPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
		topPanel.add(jb);
		topPanel.add(new JLabel("Got somethin for ye:"));
		topPanel.setBorder(BorderFactory.createLoweredBevelBorder());
		this.add(topPanel, BorderLayout.NORTH);

		jb.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				toggle();
			}

		});
		calcSize();
	}

	/**
	 * 
	 * 
	 */
	private void toggle() {
		expanded = !expanded;
		jb.setIcon(expanded ? openedIcon : closedIcon);
		refreshContentPanel();
		
		notifyExpansion(expanded);
	}

	private void notifyExpansion(boolean expanded) {
		if(callback != null){
			if(expanded)
				callback.hasExpanded();
			else
				callback.hasCollapsed();
		}
	}

	private void refreshContentPanel() {
		if (expanded) {
			this.add(this.contentPanel, BorderLayout.CENTER);
		} else {
			this.remove(this.contentPanel);
		}
		this.validate();
		calcSize();
	}

	public void setCallback(ExpansionCallback callback) {
		this.callback = callback;
	}

	@Override
	public void addNotify() {
		super.addNotify();
		calcSize();
	}

	public JPanel getContentPanel() {
		return contentPanel;
	}

	public void setContentPanel(JPanel contentPanel) {
		this.contentPanel = contentPanel;
		refreshContentPanel();
	}


	public boolean isExpanded() {
		return expanded;
	}

	public void setExpanded(boolean expanded) {
		this.expanded = expanded;
		refreshContentPanel();
	}

	/**
	 * We want the parent window to have its preferred height but the width of
	 * the hidden panel.
	 * 
	 */
	private void calcSize() {
		Window w = SwingUtilities.getWindowAncestor(this);
		if (w != null) {
			Dimension newSize1 = w.getPreferredSize();
			Dimension newSize2 = contentPanel.getPreferredSize();
			
			int maxWidth = Math.max(newSize1.width, newSize2.width);
			
			newSize1.setSize(maxWidth, newSize1.getHeight());
			w.setSize(newSize1);
			w.validate();
		}
	}

	private static void initIcons() {
		if (closedIcon == null) {
			URL url = ExpandingPanel.class.getResource("images/closed.gif");
			closedIcon = new ImageIcon(url);
		}
		if (openedIcon == null) {
			URL url = ExpandingPanel.class.getResource("images/opened.gif");
			openedIcon = new ImageIcon(url);
		}
	}

	/**
	 * 
	 * @author daniel
	 *
	 */
	public static interface ExpansionCallback {
		public void hasExpanded();

		public void hasCollapsed();
	}
}
